using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObviousCode.Stately;
using System.IO;
using StatelyCompiler;
using ObviousCode.StatelyCompiler.Validation;
using ObviousCode.Stately.Compiler.ContextMenuHandler.Values;

namespace ObviousCode.Stately.Compiler.Validation
{
    public partial class CodeValidator
    {
        public void Start(string mapFileName, Action<ValidationContext> callback)
        {
            ValidationContext context = new ValidationContext();

            context.MapFileName = mapFileName;
            context.Callback = callback;

            _stately.Start(Step.DefineCodeFile, context);
        }

        private ITransitionRequest HandleDefineCodeFile(ValidationContext context)
        {

            FileInfo file = new FileInfo(context.MapFileName);

            ValuesReader reader = new ContextMenuHandler.Values.ValuesReader();

            ValuesContext valuesContext = new ValuesContext();
            valuesContext.MapFilename = context.MapFileName;

            reader.Start(valuesContext, (c) =>
            {
                context.PrimaryCodeFileCandidate = Path.Combine(file.DirectoryName, "{0}.cs".F(valuesContext.Classname));
                context.AlternateCodeFileCandidates.Add(Path.Combine(file.DirectoryName, "{0}_stub.cs".F(valuesContext.Classname)));

                string possibleCandidate = Path.Combine(file.DirectoryName, "{0}.cs".F(file.GetBaseFileName()));

                if (context.PrimaryCodeFileCandidate != possibleCandidate)
                {
                    context.AlternateCodeFileCandidates.Add(possibleCandidate);
                }

                context.Namespace = c.Namespace;
                context.DataContext = c.DataContext;
                context.Classname = c.Classname;
            });

            return _stately.T(Step.EnsureMapFileExists, context);
        }

        private ITransitionRequest HandleEnsureMapFileExists(ValidationContext context)
        {
            if (File.Exists(context.MapFileName)) return _stately.T(Step.EnsureCodeFileExists, context);

            _stately.Derail(Step.NotifyMapFileMissing, context);
            return HaltRequest.Instance;
        }


        private ITransitionRequest HandleEnsureCodeFileExists(ValidationContext context)
        {
            if (File.Exists(context.PrimaryCodeFileCandidate)) return _stately.T(Step.RemovePreviousValidationMessages, context);

            foreach (string candidate in context.AlternateCodeFileCandidates)
            {
                if (File.Exists(candidate))
                {
                    context.PrimaryCodeFileCandidate = candidate;
                    return _stately.T(Step.RemovePreviousValidationMessages, context);
                }
            }

            _stately.Derail(Step.NotifyCodeFileMissing, context);
            return HaltRequest.Instance;
        }

        private ITransitionRequest HandleRemovePreviousValidationMessages(ValidationContext context)
        {
            if (File.Exists("validation.json"))
            {
                File.Delete("validation.json");
            }

            return _stately.T(Step.GetExpectations, context);
        }

        private ITransitionRequest HandleGetExpectations(ValidationContext context)
        {
            ValidatorExpectationBuilder builder = new ValidatorExpectationBuilder();

            bool derail = false;

            builder.MapFileMissing += (s, e) =>
            {
                _stately.Derail(Step.NotifyExpectationsBuilderUnableToLocateMapFile, context);
                derail = true;
            };

            builder.CodeFileMissing += (s, e) =>
            {
                _stately.Derail(Step.NotifyExpectationsBuilderUnableToLocateCodeFile, context);
                derail = true;
            };

            builder.ExceptionOccured += (s, e) =>
            {
                _stately.Derail(Step.Exception);
                derail = true;
            };

            builder.Start(context.MapFileName, context.PrimaryCodeFileCandidate, (c) =>
            {
                context.DefinedTransitions = c.DefinedTransitions;
                context.TransformData = c.TransformData;
            });


            if (derail) return HaltRequest.Instance;

            return _stately.T(Step.AssertExpectations, context);
        }

        private ITransitionRequest HandleAssertExpectations(ValidationContext context)
        {
            CodeFileExpectationValidator parser = new CodeFileExpectationValidator();

            parser.Start(context, (c) =>
                {

                });
            //return _stately.T(Step.NotifyMissingExpectations, context);
            //return _stately.T(Step.WriteSuccessfulValidationEndOfCodeFile, context);

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleNotifyMissingExpectations(ValidationContext context)
        {
            //return _stately.T(Step.WriteMissingExpectationsToEndOfCodeFile, context);

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleWriteMissingExpectationsToEndOfCodeFile(ValidationContext context)
        {
            //return _stately.T(Step.NotifyValidationComplete, context);

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleNotifyValidationComplete(ValidationContext context)
        {
            //return CompleteRequest.Instance

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleWriteSuccessfulValidationEndOfCodeFile(ValidationContext context)
        {
            //return _stately.T(Step.NotifyValidationComplete, context);

            throw new NotImplementedException();

        }

        public event EventHandler MapFileMissing;
        private ITransitionRequest HandleNotifyMapFileMissing(ValidationContext context)
        {

            throw new NotImplementedException();

        }

        public event EventHandler CodeFileMissing;
        private ITransitionRequest HandleNotifyCodeFileMissing(ValidationContext context)
        {

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleNotifyExpectationsBuilderUnableToLocateMapFile(ValidationContext context)
        {

            throw new NotImplementedException();

        }

        private ITransitionRequest HandleNotifyExpectationsBuilderUnableToLocateCodeFile(ValidationContext context)
        {

            throw new NotImplementedException();

        }


    }
}

